// 全局错误处理工具
import { ElMessage, ElNotification } from 'element-plus'

// 错误类型枚举
export enum ErrorType {
  NETWORK = 'NETWORK',
  AUTH = 'AUTH',
  VALIDATION = 'VALIDATION',
  BUSINESS = 'BUSINESS',
  UNKNOWN = 'UNKNOWN'
}

// 错误级别枚举
export enum ErrorLevel {
  LOW = 'LOW',
  MEDIUM = 'MEDIUM',
  HIGH = 'HIGH',
  CRITICAL = 'CRITICAL'
}

// 错误信息接口
export interface ErrorInfo {
  type: ErrorType
  level: ErrorLevel
  message: string
  code?: string | number
  details?: any
  timestamp: Date
  stack?: string
  context?: Record<string, any>
}

// 错误处理配置
interface ErrorHandlerConfig {
  showToast: boolean
  showNotification: boolean
  logToConsole: boolean
  reportToServer: boolean
  maxRetries: number
}

// 默认配置
const DEFAULT_CONFIG: ErrorHandlerConfig = {
  showToast: true,
  showNotification: false,
  logToConsole: true,
  reportToServer: false,
  maxRetries: 3
}

// 错误消息映射
const ERROR_MESSAGES: Record<string, string> = {
  // 网络错误
  'NETWORK_ERROR': '网络连接异常，请检查网络设置',
  'TIMEOUT_ERROR': '请求超时，请稍后重试',
  'CONNECTION_FAILED': '连接失败，请检查网络连接',
  
  // 认证错误
  'AUTH_FAILED': '认证失败，请重新登录',
  'TOKEN_EXPIRED': '登录已过期，请重新登录',
  'PERMISSION_DENIED': '权限不足，无法执行此操作',
  
  // 业务错误
  'MESSAGE_SEND_FAILED': '消息发送失败，请重试',
  'MESSAGE_LOAD_FAILED': '消息加载失败，请刷新重试',
  'FRIEND_LOAD_FAILED': '好友列表加载失败，请重试',
  
  // 验证错误
  'VALIDATION_FAILED': '输入信息有误，请检查后重试',
  'REQUIRED_FIELD_MISSING': '必填字段不能为空',
  
  // 通用错误
  'UNKNOWN_ERROR': '发生未知错误，请稍后重试',
  'SERVER_ERROR': '服务器错误，请稍后重试'
}

class ErrorHandler {
  private config: ErrorHandlerConfig
  private errorQueue: ErrorInfo[] = []
  private retryMap: Map<string, number> = new Map()

  constructor(config: Partial<ErrorHandlerConfig> = {}) {
    this.config = { ...DEFAULT_CONFIG, ...config }
  }

  /**
   * 处理错误
   */
  handle(error: Error | ErrorInfo | any, context?: Record<string, any>): void {
    const errorInfo = this.normalizeError(error, context)
    
    // 添加到错误队列
    this.errorQueue.push(errorInfo)
    
    // 控制台日志
    if (this.config.logToConsole) {
      this.logError(errorInfo)
    }
    
    // 显示用户提示
    this.showUserFeedback(errorInfo)
    
    // 上报服务器
    if (this.config.reportToServer) {
      this.reportError(errorInfo)
    }
    
    // 清理过期错误
    this.cleanupErrorQueue()
  }

  /**
   * 标准化错误信息
   */
  private normalizeError(error: any, context?: Record<string, any>): ErrorInfo {
    if (error && typeof error === 'object' && 'type' in error) {
      // 已经是 ErrorInfo 格式
      return {
        ...error,
        timestamp: error.timestamp || new Date(),
        context: { ...error.context, ...context }
      }
    }

    // 处理 Error 对象
    if (error instanceof Error) {
      return {
        type: this.detectErrorType(error),
        level: this.detectErrorLevel(error),
        message: this.getErrorMessage(error),
        code: (error as any).code,
        details: error,
        timestamp: new Date(),
        stack: error.stack,
        context
      }
    }

    // 处理字符串错误
    if (typeof error === 'string') {
      return {
        type: ErrorType.UNKNOWN,
        level: ErrorLevel.MEDIUM,
        message: error,
        timestamp: new Date(),
        context
      }
    }

    // 处理其他类型
    return {
      type: ErrorType.UNKNOWN,
      level: ErrorLevel.MEDIUM,
      message: '发生未知错误',
      details: error,
      timestamp: new Date(),
      context
    }
  }

  /**
   * 检测错误类型
   */
  private detectErrorType(error: Error): ErrorType {
    const message = error.message.toLowerCase()
    const name = error.name.toLowerCase()

    if (message.includes('network') || message.includes('timeout') || name.includes('network')) {
      return ErrorType.NETWORK
    }

    if (message.includes('auth') || message.includes('token') || message.includes('permission')) {
      return ErrorType.AUTH
    }

    if (message.includes('validation') || message.includes('invalid') || message.includes('required')) {
      return ErrorType.VALIDATION
    }

    if ((error as any).code && typeof (error as any).code === 'number') {
      const code = (error as any).code
      if (code >= 400 && code < 500) {
        return code === 401 || code === 403 ? ErrorType.AUTH : ErrorType.VALIDATION
      }
      if (code >= 500) {
        return ErrorType.BUSINESS
      }
    }

    return ErrorType.UNKNOWN
  }

  /**
   * 检测错误级别
   */
  private detectErrorLevel(error: Error): ErrorLevel {
    const message = error.message.toLowerCase()
    
    if (message.includes('critical') || message.includes('fatal')) {
      return ErrorLevel.CRITICAL
    }

    if (message.includes('auth') || message.includes('permission')) {
      return ErrorLevel.HIGH
    }

    if (message.includes('network') || message.includes('timeout')) {
      return ErrorLevel.MEDIUM
    }

    return ErrorLevel.LOW
  }

  /**
   * 获取友好的错误消息
   */
  private getErrorMessage(error: Error): string {
    const code = (error as any).code
    const message = error.message

    // 根据错误码获取消息
    if (code && ERROR_MESSAGES[code]) {
      return ERROR_MESSAGES[code]
    }

    // 根据错误消息匹配
    for (const [key, value] of Object.entries(ERROR_MESSAGES)) {
      if (message.toLowerCase().includes(key.toLowerCase().replace('_', ' '))) {
        return value
      }
    }

    // 返回原始消息或默认消息
    return message || ERROR_MESSAGES.UNKNOWN_ERROR
  }

  /**
   * 显示用户反馈
   */
  private showUserFeedback(errorInfo: ErrorInfo): void {
    const { level, message, type } = errorInfo

    // 根据错误级别决定显示方式
    if (level === ErrorLevel.CRITICAL || level === ErrorLevel.HIGH) {
      if (this.config.showNotification) {
        ElNotification({
          title: '错误',
          message,
          type: 'error',
          duration: 0, // 不自动关闭
          showClose: true
        })
      }
    } else if (this.config.showToast) {
      ElMessage({
        message,
        type: 'error',
        duration: level === ErrorLevel.MEDIUM ? 5000 : 3000,
        showClose: true
      })
    }
  }

  /**
   * 记录错误日志
   */
  private logError(errorInfo: ErrorInfo): void {
    const { type, level, message, code, stack, context } = errorInfo
    
    const logData = {
      type,
      level,
      message,
      code,
      timestamp: errorInfo.timestamp.toISOString(),
      context,
      stack
    }

    if (level === ErrorLevel.CRITICAL) {
      console.error('🔴 Critical Error:', logData)
    } else if (level === ErrorLevel.HIGH) {
      console.error('🟠 High Priority Error:', logData)
    } else if (level === ErrorLevel.MEDIUM) {
      console.warn('🟡 Medium Priority Error:', logData)
    } else {
      console.log('🔵 Low Priority Error:', logData)
    }
  }

  /**
   * 上报错误到服务器
   */
  private async reportError(errorInfo: ErrorInfo): Promise<void> {
    try {
      // 这里可以集成错误上报服务，如 Sentry
      const reportData = {
        type: errorInfo.type,
        level: errorInfo.level,
        message: errorInfo.message,
        code: errorInfo.code,
        timestamp: errorInfo.timestamp.toISOString(),
        userAgent: navigator.userAgent,
        url: window.location.href,
        context: errorInfo.context,
        stack: errorInfo.stack
      }

      // 发送到错误收集服务
      // await fetch('/api/errors', {
      //   method: 'POST',
      //   headers: { 'Content-Type': 'application/json' },
      //   body: JSON.stringify(reportData)
      // })
      
      console.log('Error reported:', reportData)
    } catch (err) {
      console.warn('Failed to report error:', err)
    }
  }

  /**
   * 清理错误队列
   */
  private cleanupErrorQueue(): void {
    const maxAge = 5 * 60 * 1000 // 5分钟
    const now = Date.now()
    
    this.errorQueue = this.errorQueue.filter(
      error => now - error.timestamp.getTime() < maxAge
    )

    // 限制队列大小
    if (this.errorQueue.length > 100) {
      this.errorQueue = this.errorQueue.slice(-50)
    }
  }

  /**
   * 重试操作
   */
  async retry<T>(
    operation: () => Promise<T>,
    key: string,
    maxRetries: number = this.config.maxRetries
  ): Promise<T> {
    const currentRetries = this.retryMap.get(key) || 0
    
    try {
      const result = await operation()
      // 成功后清除重试计数
      this.retryMap.delete(key)
      return result
    } catch (error) {
      if (currentRetries < maxRetries) {
        this.retryMap.set(key, currentRetries + 1)
        
        // 指数退避延迟
        const delay = Math.min(1000 * Math.pow(2, currentRetries), 10000)
        await new Promise(resolve => setTimeout(resolve, delay))
        
        return this.retry(operation, key, maxRetries)
      } else {
        // 达到最大重试次数，清除计数并抛出错误
        this.retryMap.delete(key)
        throw error
      }
    }
  }

  /**
   * 获取错误统计
   */
  getErrorStats(): {
    total: number
    byType: Record<ErrorType, number>
    byLevel: Record<ErrorLevel, number>
    recent: ErrorInfo[]
  } {
    const stats = {
      total: this.errorQueue.length,
      byType: {} as Record<ErrorType, number>,
      byLevel: {} as Record<ErrorLevel, number>,
      recent: this.errorQueue.slice(-10)
    }

    // 初始化计数器
    Object.values(ErrorType).forEach(type => {
      stats.byType[type] = 0
    })
    Object.values(ErrorLevel).forEach(level => {
      stats.byLevel[level] = 0
    })

    // 统计错误
    this.errorQueue.forEach(error => {
      stats.byType[error.type]++
      stats.byLevel[error.level]++
    })

    return stats
  }

  /**
   * 清除所有错误
   */
  clearErrors(): void {
    this.errorQueue = []
    this.retryMap.clear()
  }

  /**
   * 更新配置
   */
  updateConfig(config: Partial<ErrorHandlerConfig>): void {
    this.config = { ...this.config, ...config }
  }
}

// 创建全局错误处理器实例
export const errorHandler = new ErrorHandler()

// 全局错误处理函数
export const handleError = (error: any, context?: Record<string, any>) => {
  errorHandler.handle(error, context)
}

// 重试函数
export const retryOperation = <T>(
  operation: () => Promise<T>,
  key: string,
  maxRetries?: number
): Promise<T> => {
  return errorHandler.retry(operation, key, maxRetries)
}

// 创建错误信息
export const createError = (
  type: ErrorType,
  level: ErrorLevel,
  message: string,
  code?: string | number,
  details?: any
): ErrorInfo => {
  return {
    type,
    level,
    message,
    code,
    details,
    timestamp: new Date()
  }
}

// Vue 错误处理插件
export const errorHandlerPlugin = {
  install(app: any) {
    // 全局错误处理
    app.config.errorHandler = (error: Error, instance: any, info: string) => {
      handleError(error, {
        component: instance?.$options.name || 'Unknown',
        errorInfo: info,
        props: instance?.$props
      })
    }

    // 全局属性
    app.config.globalProperties.$handleError = handleError
    app.config.globalProperties.$retryOperation = retryOperation
  }
}

// 未捕获的Promise错误处理
window.addEventListener('unhandledrejection', (event) => {
  handleError(event.reason, {
    type: 'unhandledrejection',
    promise: event.promise
  })
})

// 未捕获的JavaScript错误处理
window.addEventListener('error', (event) => {
  handleError(new Error(event.message), {
    type: 'javascript',
    filename: event.filename,
    lineno: event.lineno,
    colno: event.colno
  })
})